from django.shortcuts import render
from django.views import View
from django import http
from django.core.paginator import Paginator, EmptyPage
from django.utils import timezone

from contents.utils import get_categories
from .models import GoodsCategory, SKU, GoodsVisitCount
from .utils import get_breadcrumb
from meiduo_mall.utils.response_code import RETCODE
import logging

logger = logging.getLogger('django')

class ListView(View):
    """商品列表界面"""
    def get(self, request, category_id, page_num):

        try:
            # 校验三级类别id
            category = GoodsCategory.objects.get(id=category_id)
        except GoodsCategory.DoesNotExist:
            return http.HttpResponseForbidden('category_id不存在')
        try:
            if category.parent.parent is None:
                return http.HttpResponseForbidden('类别有误')
        except:
            return http.HttpResponseForbidden('类别有误')
        # 获取排序规则数据
        sort = request.GET.get('sort')
        if sort == 'price':
            sort_field = 'price'
        elif sort == 'hot':
            sort_field = 'sales'
        else:
            sort = 'default'
            sort_field = '-update_time'
        # 查询当前三级类型下的所有sku
        sku_qs = category.sku_set.filter(is_launched=True).order_by(sort_field)
        # 定义一个变量表示每页显示多少条
        # page = 5
        # total_num = sku_qs.count()  # 数据总数量  16
        # # 17 // 5 + total_page % 5
        # dy = 1 if (total_num % 5) else 0
        # # 计算总页数 = 取正页 + 多余页(0, 1)
        # total_page = total_num // page + dy
        # page_num = int(page_num)
        # # 指定页显示的数据
        # page_sku = sku_qs[(page_num - 1) * page: page_num * page]
        # Paginator(object_list='要分页的所有数据', per_page='每页显示多少条')
        # 创建分页器对象
        paginator = Paginator(object_list=sku_qs, per_page=5)
        # 获取总页数据
        total_page = paginator.num_pages
        try:
            # 获取指定页数据
            page_sku = paginator.page(page_num)
        except EmptyPage as e:
            logger.error(e)
            return http.HttpResponseForbidden('老实点,没有下一页了')





        context = {
            'categories': get_categories(),  # 商品类别
            'breadcrumb': get_breadcrumb(category),  # 面包屑导航数据
            'category':  category,  # 当前三级类别模型对象
            'sort': sort,  # 排序字段
            'page_skus': page_sku,  # 指定页sku数据
            'page_num': page_num,  # 当前显示第几页数据
            'total_page': total_page,  # 总页数据
        }
        return render(request, 'list.html', context)


class HotGoodsView(View):
    """热销排行"""
    def get(self, request, category_id):
        # 1.校验
        try:
            # 校验三级类别id
            category = GoodsCategory.objects.get(id=category_id)
        except GoodsCategory.DoesNotExist:
            return http.HttpResponseForbidden('category_id不存在')
        try:
            if category.parent.parent is None:
                return http.HttpResponseForbidden('类别有误')
        except:
            return http.HttpResponseForbidden('类别有误')
        # 2.获取当前三级类别下销量最好的前两个sku
        sku_qs = category.sku_set.order_by('-sales')[:2]
        # 3.模型转字典
        sku_list = []
        for sku in sku_qs:
            sku_list.append({
                'id': sku.id,
                'name': sku.name,
                'default_image_url': sku.default_image.url,
                'price': sku.price
            })
        # 响应
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'hot_skus': sku_list})


class DetailView(View):
    """商品详情"""
    def get(self, request, sku_id):

        try:
            sku = SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return render(request, '404.html')

        category = sku.category  # 获取当前sku所对应的三级分类

        # 查询当前sku所对应的spu
        spu = sku.spu

        """1.准备当前商品的规格选项列表 [8, 11]"""
        # 获取出当前正显示的sku商品的规格选项id列表
        current_sku_spec_qs = sku.specs.order_by('spec_id')
        current_sku_option_ids = []  # [8, 11]
        for current_sku_spec in current_sku_spec_qs:
            current_sku_option_ids.append(current_sku_spec.option_id)

        """2.构造规格选择仓库
        {(8, 11): 3, (8, 12): 4, (9, 11): 5, (9, 12): 6, (10, 11): 7, (10, 12): 8}
        """
        # 构造规格选择仓库
        temp_sku_qs = spu.sku_set.all()  # 获取当前spu下的所有sku
        # 选项仓库大字典
        spec_sku_map = {}  # {(8, 11): 3, (8, 12): 4, (9, 11): 5, (9, 12): 6, (10, 11): 7, (10, 12): 8}
        for temp_sku in temp_sku_qs:
            # 查询每一个sku的规格数据
            temp_spec_qs = temp_sku.specs.order_by('spec_id')
            temp_sku_option_ids = []  # 用来包装每个sku的选项值
            for temp_spec in temp_spec_qs:
                temp_sku_option_ids.append(temp_spec.option_id)
            spec_sku_map[tuple(temp_sku_option_ids)] = temp_sku.id

        """3.组合 并找到sku_id 绑定"""
        spu_spec_qs = spu.specs.order_by('id')  # 获取当前spu中的所有规格

        for index, spec in enumerate(spu_spec_qs):  # 遍历当前所有的规格
            spec_option_qs = spec.options.all()  # 获取当前规格中的所有选项
            temp_option_ids = current_sku_option_ids[:]  # 复制一个新的当前显示商品的规格选项列表
            for option in spec_option_qs:  # 遍历当前规格下的所有选项
                temp_option_ids[index] = option.id  # [8, 12]
                option.sku_id = spec_sku_map.get(tuple(temp_option_ids))  # 给每个选项对象绑定下他sku_id属性

            spec.spec_options = spec_option_qs  # 把规格下的所有选项绑定到规格对象的spec_options属性上

        context = {
            'categories': get_categories(),  # 商品分类
            'breadcrumb': get_breadcrumb(category),  # 面包屑导航
            'sku': sku,  # 当前要显示的sku模型对象
            'category': category,  # 当前的显示sku所属的三级类别
            'spu': spu,  # sku所属的spu
            'spec_qs': spu_spec_qs,  # 当前商品的所有规格数据
        }
        return render(request, 'detail.html', context)


class GoodsVisitView(View):
    """三级类别每日访问量"""
    def post(self, request, category_id):
        # 1. 校验
        try:
            # 校验三级类别id
            category = GoodsCategory.objects.get(id=category_id)
        except GoodsCategory.DoesNotExist:
            return http.HttpResponseForbidden('category_id不存在')
        try:
            if category.parent.parent is None:
                return http.HttpResponseForbidden('类别有误')
        except:
            return http.HttpResponseForbidden('类别有误')

        # timezone.localtime()  # 获取当前时间
        # date = timezone.localdate()  # 获取当前日期
        date = timezone.now()  # 获取当前的日期和时间
        try:
            # 2. 查询当前三级类型今日是否访问
            # 访问过,修count
            goods_visit = GoodsVisitCount.objects.get(category=category, date=date)
        except GoodsVisitCount.DoesNotExist:
            # 没有访问过,新增
            goods_visit = GoodsVisitCount(category=category)

        # 修改count及保存
        goods_visit.count += 1
        goods_visit.save()
        # 响应
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})